package com.santu.edu.supporter.biz.order.kd.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.santu.edu.supporter.biz.buildings.pojo.dto.BuildingsDTO;
import com.santu.edu.supporter.biz.buildings.serice.BuildingsService;
import com.santu.edu.supporter.biz.order.common.pojo.enums.OrderStatusEnum;
import com.santu.edu.supporter.biz.order.kd.dao.KuaidiOrderDao;
import com.santu.edu.supporter.biz.order.kd.pojo.dto.KdOrderDTO;
import com.santu.edu.supporter.biz.order.kd.pojo.dto.KdOrderInfoDTO;
import com.santu.edu.supporter.biz.order.kd.pojo.params.KdOrderAddParam;
import com.santu.edu.supporter.biz.order.kd.pojo.params.KdOrderUpdateParam;
import com.santu.edu.supporter.biz.order.kd.service.KuaidiService;
import com.santu.edu.supporter.biz.pay.pojo.constants.WxNotifyConstants;
import com.santu.edu.supporter.biz.pay.pojo.dto.WxChatBasePayDTO;
import com.santu.edu.supporter.biz.pay.pojo.dto.WxChatPayDTO;
import com.santu.edu.supporter.biz.pay.service.WxOrderService;
import com.santu.edu.supporter.biz.user.pojo.dto.UserAddressDTO;
import com.santu.edu.supporter.biz.user.pojo.dto.UserDTO;
import com.santu.edu.supporter.biz.user.service.UserAdressService;
import com.santu.edu.supporter.biz.user.service.UserService;
import com.santu.edu.supporter.exception.BizException;
import com.santu.edu.supporter.exception.CustomError;
import com.santu.edu.supporter.interceptor.UserThreadLocal;
import com.santu.edu.supporter.util.PageData;
import com.santu.edu.supporter.util.UuidUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author luoyaoqi
 * @createTime 2024/2/21
 * @description
 */
@Service
@RequiredArgsConstructor
public class KuaidiServiceImpl implements KuaidiService {

    private final KuaidiOrderDao kdOrderDao;

    private final UserService userService;

    private final WxOrderService wxOrderService;

    private final BuildingsService buildingsService;

    private final UserAdressService adressService;

    @Override
    public WxChatPayDTO addOrder(KdOrderAddParam addParam) {
        String userId = UserThreadLocal.get();
        UserDTO userDTO = userService.getUserById(userId);
        String orderId = UuidUtils.getOrderId();
        KdOrderDTO dto = KdOrderDTO.createItem(orderId, addParam);
        dto.setUserId(userId)
                .setSchoolId(userDTO.getSchoolId());
        //调用微信支付API
        WxChatBasePayDTO basePayDto = WxChatBasePayDTO.builder()
                .openId(userId)
                .title("校园快递代拿")
                .orderId(orderId)
                .price(dto.getPrice().divide(new BigDecimal(100)))
                .notify(WxNotifyConstants.RUN_ERRANDS_NOTIFY)
                .build();
        WxChatPayDTO payDto = wxOrderService.pay(basePayDto);
        kdOrderDao.addOrder(dto);
        return payDto;
    }



    @Override
    public WxChatPayDTO getPayInfoById(String orderId) {
        String userId = UserThreadLocal.get();
        KdOrderDTO kdOrderDTO = checkOrderIsExist(orderId);
        //调用微信支付API
        WxChatBasePayDTO basePayDto = WxChatBasePayDTO.builder()
                .openId(userId)
                .title("校园快递代拿")
                .orderId(orderId)
                .price(kdOrderDTO.getPrice().divide(new BigDecimal(100)))
                .notify(WxNotifyConstants.RUN_ERRANDS_NOTIFY)
                .build();
        return wxOrderService.pay(basePayDto);
    }



    @Override
    public Boolean updateOrder(KdOrderUpdateParam updateParam) {
        //当前订单是否存在
        checkOrderIsExist(updateParam.getOrderId());
        KdOrderDTO dto = KdOrderDTO.createItem(updateParam);
        kdOrderDao.updateOrder(dto);
        return true;
    }


    @Override
    public Boolean cancelOrder(String orderId) {
        //当前订单是否存在
        KdOrderDTO dto = checkOrderIsExist(orderId);
        if (dto.getOrderType().equals(OrderStatusEnum.TO_BE_PAID)) {
            kdOrderDao.updateOrderStatus(orderId, OrderStatusEnum.TO_BE_PAID, OrderStatusEnum.CANCEL);
        } else {
            throw BizException.causeBy(CustomError.ORDER_NOT_CANCEL);
        }
        return true;
    }

    @Override
    public PageData<KdOrderInfoDTO> getOrderList(Integer orderType, int page, int size) {
        String userId = UserThreadLocal.get();
        String schoolId = userService.getUserById(userId).getSchoolId();
        PageData<KdOrderDTO> orderPage = kdOrderDao.getOrderPage(schoolId, userId, orderType, page, size);
        List<KdOrderDTO> dataList = orderPage.getList();
        if (CollUtil.isEmpty(dataList)) {
            return new PageData<>(Collections.emptyList(), orderPage.getPages(), orderPage.getTotal());
        }
        Set<String> buildingsIdList = new HashSet<>();
        List<String> addressIdList = new ArrayList<>();
        dataList.forEach(item -> {
            buildingsIdList.add(item.getBuildingsId());
            addressIdList.add(item.getAddressId());
        });
        List<UserAddressDTO> addressDTOList = adressService.getAddressByIdList(addressIdList);
        for (UserAddressDTO addressDTO : addressDTOList) {
            buildingsIdList.add(addressDTO.getBuildingsId());
        }
        Map<String, UserAddressDTO> addressMap = addressDTOList.stream().collect(Collectors.toMap(UserAddressDTO::getAddressId, item -> item));
        Map<String, String> buildMap = buildingsService.getBuildsByIdList(new ArrayList<>(buildingsIdList)).stream().collect(Collectors.toMap(BuildingsDTO::getBuildingsId, BuildingsDTO::getBuildingsName));
        List<KdOrderInfoDTO> resultList = dataList.stream().map(item -> {
            KdOrderInfoDTO dto = KdOrderInfoDTO.createItem(item);
            dto.setBuildingsInfo(item.getBuildingsId(), buildMap.get(item.getBuildingsId()));
            UserAddressDTO addressDTO = addressMap.get(item.getAddressId());
            dto.setAddressInfo(addressDTO, buildMap.get(addressDTO.getBuildingsId()));
            return dto;
        }).collect(Collectors.toList());
        return new PageData<>(resultList, orderPage.getPages(), orderPage.getTotal());
    }

    @Override
    public void updateOrderStatus(String orderId, OrderStatusEnum orderStatus, OrderStatusEnum nowOrderStatus) {
        kdOrderDao.updateOrderStatus(orderId, orderStatus, nowOrderStatus);
    }

    @Override
    public Boolean orderComplete(String orderId) {
        KdOrderDTO dto = checkOrderIsExist(orderId);
        if (dto.getOrderType().equals(OrderStatusEnum.IN_PROGRESS)) {
            kdOrderDao.updateOrderStatus(orderId, OrderStatusEnum.IN_PROGRESS, OrderStatusEnum.FINISHED);
        } else {
            throw BizException.causeBy(CustomError.ORDER_NOT_COMPLETE);
        }
        return true;
    }

    @Override
    public Boolean goodComplete(String orderId) {
        checkOrderIsExist(orderId);
        kdOrderDao.updateGoodComplete(orderId);
        return true;
    }


    private KdOrderDTO checkOrderIsExist(String orderId) {
        KdOrderDTO orderById = kdOrderDao.getOrderById(orderId);
        if (orderById == null) {
            throw BizException.causeBy(CustomError.ORDER_NOT_EXIST);
        }
        return orderById;
    }
}
